home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_ImportInt / GraphicImport.m < prev    next >
Encoding:
Text File  |  1992-12-19  |  16.9 KB  |  773 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34. *    GraphicImport.m
  35. *
  36. *    This subclass of handles much of the overhead for imported
  37. *    files such as TIFF files and EPS files. Subclasses of this object
  38. *    provide the specific methods that differentiate the two.
  39. *
  40. *    Version:    2.0
  41. *    Author:    Ken Fromm
  42. *    History:
  43. *            03-20-91        Created the file.
  44. */
  45.  
  46. #import "GraphicImport.h"
  47. #import "DrawingView.h"
  48. #import "DrawingViewWraps.h"
  49. #import "NXBitmapImageRepSub.h"
  50. #import "NXEPSImageRepSub.h"
  51. #import "ResourcePanel.h"
  52.  
  53. #import <appkit/Font.h>
  54. #import <appkit/NXImage.h>
  55. #import <appkit/Panel.h>
  56. #import <appkit/nextstd.h>
  57.  
  58. #import <objc/List.h>
  59. #import <dpsclient/wraps.h>
  60. #import <streams/streamsimpl.h>
  61.  
  62. #import <mach.h>
  63.  
  64. static const char    *ImageErrorString = "PostScript errors have been encountered in this file. The text of the errors can be found in the console output.";
  65.  
  66. @implementation GraphicImport
  67.  
  68. /*
  69.  *    Initializes a new GraphicImport object associated with the file.
  70.  *    If an EPS file, then check the resources. Three routes are possible.
  71.  *    The first makes everything as ok. The second cancels the import.
  72.  *    The third makes the file as unimageable.
  73.  */
  74. - initFromFile:(const char *) file
  75. {
  76.     char            *end;
  77.  
  78.     ResourceList        resourceList;
  79.  
  80.     self = [super  init];
  81.  
  82.     gflags.new = YES;
  83.     gflags.dirty = YES;
  84.     [self  setFilename:file];
  85.     image = [[NXImage  alloc]  init];
  86.     if (image)
  87.     {
  88.         end = strrchr(file, '.');
  89.         if (end)
  90.         {
  91.             if (strncmp(end, ".ps", 3) == 0 || strncmp(end, ".eps", 4) == 0)
  92.             {
  93.                 imagerep = [[NXEPSImageRepSub  alloc]  initFromFile:file];
  94.                 if (imagerep)
  95.                 {
  96.                     /*  Check the epsf file and list any that are unavailable. */
  97.                     if (![imagerep  checkResources:&resourceList] ||
  98.                         ![self  listUnavailableResources:&resourceList])
  99.                     {
  100.                         [imagerep  free];
  101.                         imagerep = NULL;
  102.                     }
  103.                 }
  104.                 else
  105.                     Notify("Import Error", "Unable to open file.");
  106.             }
  107.             else if (strncmp(end, ".tiff", 5) == 0)
  108.             {
  109.                 imagerep = [[NXBitmapImageRepSub  alloc]  initFromFile:file];
  110.                 if (!imagerep)
  111.                     Notify("Import Error", "Unable to open file.");
  112.             }
  113.         }
  114.     }
  115.     else
  116.         Notify("Import Error", "Unable to open file.");
  117.  
  118.     if (!imagerep)
  119.     {
  120.         [self  free];
  121.         self = nil;
  122.     }
  123.  
  124.     return self;
  125. }
  126.  
  127. /*
  128. *    Create a new object from a stream.
  129. */
  130. - initFromStream:(NXStream *) stream
  131. {
  132.     int            len, maxlen;
  133.  
  134.     char            *data;
  135.  
  136.     ResourceList        resourceList;
  137.  
  138.     self = [super  init];
  139.  
  140.     gflags.new = YES;
  141.     gflags.dirty = YES;
  142.     image = [[NXImage  alloc]  init];
  143.     if (image)
  144.     {
  145.         NXGetMemoryBuffer(stream, &data, &len, &maxlen);
  146.         if (strncmp(data, "%!PS-Adobe-", 11) == 0)
  147.         {
  148.             imagerep = [[NXEPSImageRepSub  alloc]  initFromStream:stream];
  149.             if (imagerep)
  150.             {
  151.                 /* Check the epsf file and list any that are unavailable. */
  152.                 if (![imagerep  checkResources:&resourceList] ||
  153.                     ![self  listUnavailableResources:&resourceList])
  154.                 {
  155.                     [imagerep  free];
  156.                     imagerep = NULL;
  157.                 }
  158.             }
  159.             else
  160.                 Notify("Import Error", "Unable to open file.");
  161.         }
  162.         else
  163.         {
  164.             imagerep = [[NXBitmapImageRepSub  alloc]  initFromStream:stream];
  165.             if (!imagerep)
  166.                 Notify("Import Error", "Unable to open file.");
  167.         }
  168.     }
  169.     else
  170.         Notify("Import Error", "Unable to open file.");
  171.  
  172.     if (!imagerep)
  173.     {
  174.         [self  free];
  175.         self = nil;
  176.     }
  177.  
  178.     return self;
  179. }
  180.  
  181. - (BOOL) listUnavailableResources:(ResourceList *) resourceList;
  182. {
  183.     BOOL        unavailable;
  184.  
  185.     int            i, tag;
  186.  
  187.     tag = NX_OKTAG;
  188.     unavailable = NO;
  189.     for (i = 0; i < RES_NUMTYPES; i++)
  190.         unavailable = unavailable | (resourceList->types[i] != NULL);
  191.     
  192.     if (unavailable)
  193.     {
  194.         tag = [[NXApp  resourcePanel]  runModalWithList:resourceList  andName:filename];
  195.         if (tag == NX_CANCELTAG)
  196.         {
  197.             [imagerep  free];
  198.             imagerep = NULL;
  199.         }
  200.         else if (tag == NX_ALERTOTHER)
  201.             gflags.unimageable = YES;
  202.     }
  203.  
  204.     for (i = 0; i < RES_NUMTYPES; i++)
  205.         [resourceList->types[i]  free];
  206.  
  207.     return (tag != NX_CANCELTAG);
  208. }
  209.  
  210. /*
  211. *    Used when printing. Add the resources used in this file
  212. *    to the list passed in if the file is in the rectangle.
  213. */
  214. - addResources:(Resource *) resourceDoc  for:(NXRect *) r
  215. {
  216.     if (!r || NXIntersectsRect(r, &bounds))
  217.         [imagerep  addResources:resourceDoc  forFile:filename];
  218.     
  219.     return self;
  220. }
  221.  
  222. - free
  223. {
  224.     [image  free];
  225.     [imagerep  free];
  226.  
  227.     return [super  free];
  228. }
  229.  
  230. - freeTemp
  231. {
  232.     return [super  free];
  233. }
  234.  
  235. - copy
  236. {
  237.     id    new;
  238.  
  239.     new = [super copy];
  240.     [new  setFilename:filename];
  241.     [new  setImage:image];
  242.     [new  setImageRep:imagerep];
  243.  
  244.     return new;
  245. }
  246.  
  247. - setFilename:(const char *) file
  248. {
  249.     if (file)
  250.         filename = NXUniqueString(file);
  251.  
  252.     return self;
  253. }
  254.  
  255. /* Used when producing a copy of this object. */
  256. - setImage:anImage
  257. {
  258.     image = anImage;
  259.  
  260.     return self;
  261. }
  262.  
  263. /* Used when producing a copy of this object. */
  264. - setImageRep:anImageRep
  265. {
  266.     imagerep = anImageRep;
  267.  
  268.     return self;
  269. }
  270.  
  271. - setSelected:(BOOL) flag
  272. {
  273.     gflags.selected = flag;
  274.  
  275.     return self;
  276. }
  277.  
  278. - (BOOL) selected
  279. {
  280.     return (BOOL) gflags.selected;
  281. }
  282.  
  283. - (BOOL) error
  284. {
  285.     return gflags.error;
  286. }
  287.  
  288. /*
  289. *    pt_num is the changing control point. pt holds the relative change in each coordinate. 
  290. *    The relative is needed and not the absolute because the closest inside control point
  291. *    changes when one of the outside points change.
  292. */
  293. - setPoint:(int) pt_num  :(const NXPoint *) pt
  294. {    
  295.     int            row, col;
  296.  
  297.     if (pt->x || pt->y)
  298.     {
  299.         gflags.dirty = YES;
  300.         col = pt_num % 3;
  301.         switch (col)
  302.         {
  303.             case LEFT:
  304.                 bounds.origin.x += pt->x;    
  305.                 bounds.size.width -= pt->x;
  306.                 break;
  307.             case RIGHT:
  308.                 bounds.size.width += pt->x;            
  309.                 break;
  310.         }
  311.  
  312.         row = pt_num/3;
  313.         switch (row)
  314.         {
  315.             case TOP:
  316.                 bounds.size.height += pt->y;
  317.                 break;
  318.             case BOTTOM:
  319.                 bounds.origin.y += pt->y;
  320.                 bounds.size.height -= pt->y;
  321.                 break;
  322.         }
  323.     }
  324.  
  325.     return self;
  326. }
  327.  
  328. - setSize:(const NXSize *) aSize
  329. {
  330.     if (bounds.size.width != aSize->width && bounds.size.height != aSize->height)
  331.     {
  332.         gflags.dirty = YES;
  333.         bounds.size = *aSize;
  334.     }
  335.  
  336.     return self;
  337. }
  338.  
  339. - setOrigin:(const NXPoint *) pt
  340. {    
  341.     bounds.origin = *pt;
  342.  
  343.     return self;
  344. }
  345.  
  346. - setBounds:(const NXRect *) aRect
  347. {
  348.     [self  setSize:&aRect->size];
  349.     [self  setOrigin:&aRect->origin];
  350.  
  351.     return self;
  352. }
  353.  
  354. /*    The pt argument holds the relative point change. */
  355. - moveAll:(const NXPoint *) pt
  356. {
  357.     bounds.origin.x += pt->x;
  358.     bounds.origin.y += pt->y;
  359.  
  360.     return self;
  361. }
  362.  
  363. /* Given the point number, return the point. */
  364. - getPoint:(int) pt_num  :(NXPoint *) pt
  365. {    
  366.     pt->x = bounds.origin.x + (pt_num % 3) * (bounds.size.width/2.0);
  367.     pt->y = bounds.origin.y + bounds.size.height - (pt_num/3) * (bounds.size.height/2.0);
  368.     
  369.     return self;
  370. }
  371.  
  372. /*
  373. *    Returns the bounding box of the file.
  374. */
  375. - getBounds:(NXRect *)aRect
  376. {
  377.     *aRect = bounds;
  378.  
  379.     return self;
  380. }
  381.  
  382. /* 
  383. *    This method constains the point to the bounds of the view. The
  384. *    constaining is dependent on the control point that has been selected.
  385. */
  386. - constrainPoint:(NXPoint *)aPt  forPtNum:(int *) pt_num
  387.         inRect:(const NXRect *) viewRect  withFlags:(int) flags
  388. {
  389.     int            row, col,
  390.                 directionx, directiony;
  391.  
  392.     float            aspect_ratio;
  393.  
  394.     NXSize        proposed, original;
  395.  
  396.     aPt->x = MAX(viewRect->origin.x, aPt->x);
  397.     aPt->x = MIN(viewRect->origin.x + viewRect->size.width, aPt->x);
  398.     aPt->y = MAX(viewRect->origin.y, aPt->y);        
  399.     aPt->y = MIN(viewRect->origin.y + viewRect->size.height, aPt->y);
  400.  
  401.     [imagerep  getSize:&original];
  402.  
  403.     col = *pt_num % 3;
  404.     row = *pt_num/3;
  405.     directionx = directiony = 0;
  406.     switch (col)
  407.     {
  408.         case LEFT:
  409.             proposed.width = bounds.origin.x + bounds.size.width - aPt->x;
  410.             directionx =1;    
  411.             break;        
  412.         case MIDDLE:
  413.             proposed.width = bounds.size.width;
  414.             aPt->x = bounds.origin.x + bounds.size.width/2.0;
  415.             break;
  416.         case RIGHT:
  417.             proposed.width = aPt->x - bounds.origin.x;
  418.             directionx = -1;                
  419.             break;
  420.     }
  421.  
  422.     switch (row)
  423.     {
  424.         case TOP:
  425.             proposed.height = aPt->y - bounds.origin.y;
  426.             directiony = -1;
  427.             break;            
  428.         case MIDDLE:
  429.             proposed.height = bounds.size.height;
  430.             aPt->y = bounds.origin.y + bounds.size.height/2.0;
  431.             break;
  432.         case BOTTOM:
  433.             proposed.height = bounds.origin.y + bounds.size.height - aPt->y;
  434.             directiony = 1;    
  435.             break;
  436.     }
  437.  
  438.     /* Constrain to the ratio of width vs. height. If new use the original ratio. */    
  439.     if ((flags & NX_SHIFTMASK) == NX_SHIFTMASK || gflags.new)
  440.     {
  441.         if (col != MIDDLE && row != MIDDLE)
  442.         {
  443.             if (gflags.new)
  444.                 aspect_ratio = original.width/original.height;
  445.             else
  446.                 aspect_ratio = bounds.size.width/bounds.size.height;
  447.             if (proposed.width < SIZE_MIN || proposed.height < SIZE_MIN)
  448.             {
  449.                 if (aspect_ratio > 1.0)
  450.                 {
  451.                     aPt->x = aPt->x + directionx * (proposed.width - SIZE_MIN * aspect_ratio);
  452.                     aPt->y = aPt->y + directiony * (proposed.height - SIZE_MIN);
  453.                 }
  454.                 else
  455.                 {
  456.                     aPt->x = aPt->x + directionx * (proposed.width - SIZE_MIN);
  457.                     aPt->y = aPt->y + directiony * (proposed.height - SIZE_MIN / aspect_ratio);
  458.                 }
  459.             }
  460.             else
  461.             {
  462.                 if (proposed.width/proposed.height > aspect_ratio)
  463.                     aPt->x = aPt->x + directionx *
  464.                         (proposed.width - proposed.height * aspect_ratio);
  465.                 else
  466.                     aPt->y = aPt->y + directiony *
  467.                         (proposed.height - proposed.width / aspect_ratio);
  468.             }
  469.         }
  470.         else
  471.         {
  472.             [self  getPoint:*pt_num :aPt];
  473.         }
  474.     }
  475.     else
  476.     {
  477.         if (proposed.width < SIZE_MIN)
  478.             aPt->x = aPt->x + (proposed.width - SIZE_MIN) * directionx;
  479.         if (proposed.height < SIZE_MIN)
  480.             aPt->y = aPt->y + (proposed.height - SIZE_MIN) * directiony;
  481.     }
  482.  
  483.     return self;
  484. }
  485.  
  486. /*
  487. *    Check for a control point hit. No need to perform the hit detection in
  488. *    the server since its a simple rectangle intersection check. Return the
  489. *    point number hit in the pt_num argument. The numbering starts in
  490. *    the lower left and goes left to right and bottom to top.
  491. */
  492. - hitControl:(const NXRect *) hitRect  :(int *) pt_num  forSize:(float) size
  493. {
  494.     int        i, j;
  495.  
  496.     float        halfc, halfw, halfh;
  497.  
  498.     NXRect    knobRect;
  499.  
  500.     knobRect.size.width = knobRect.size.height = size;
  501.     halfc = knobRect.size.width/2;
  502.     halfw = bounds.size.width/2;
  503.     halfh = bounds.size.height/2;
  504.     for (i=0; i < 3; i ++)
  505.     {
  506.         for (j = 0; j < 3; j++)
  507.         {
  508.             if (!(i == MIDDLE && j == MIDDLE))
  509.             {
  510.                 knobRect.origin.x = bounds.origin.x +  j * halfw - halfc;
  511.                 knobRect.origin.y = bounds.origin.y + bounds.size.height - i * halfh - halfc;
  512.                 if (NXIntersectsRect(hitRect, &knobRect))
  513.                 {
  514.                     *pt_num = i * 3 + j;
  515.                     return self;
  516.                 }
  517.             }
  518.         }
  519.     }
  520.  
  521.     return nil;
  522. }
  523.  
  524. /*
  525. *    Check for hit dectection on the object. Since the hitpoint and the
  526. *    object is a rectangle just perform a rectangle intersection check.
  527. */
  528. - hitObject:(UPath *) hitUpath
  529. {
  530.     NXRect    hitRect;
  531.  
  532.     NXSetRect(&hitRect, hitUpath->pts[0], hitUpath->pts[1],
  533.         hitUpath->pts[2] - hitUpath->pts[0],
  534.             hitUpath->pts[3] - hitUpath->pts[1]);
  535.  
  536.     if (NXIntersectsRect(&hitRect, &bounds))
  537.         return self;
  538.  
  539.     return nil;
  540. }
  541.  
  542. /*
  543. *    Place the point locations and the chararacters for the control
  544. *    points into the user path description passed in. In this case, the
  545. *    xyshow operator is used instead of a user path. But because the
  546. *    xyshow operator takes the same data format as the user path,
  547. *    the buffers for the user paths are used.  The position of the point
  548. *    is calculated relative to the position of the previous point. If
  549. *    this is the first set of points in the description then put the
  550. *    absolute values in place, otherwise use the lastPoint 
  551. *    argument to calculate the displacement.
  552. */
  553. - putControlPoints:(UPath *)buffer  forRect:(NXRect *)r  :(NXPoint *) lastPoint
  554. {
  555.     int            i, j;
  556.  
  557.     NXPoint        pt;
  558.  
  559.     NXRect        bRect;
  560.     
  561.     [self  getBounds:&bRect]; 
  562.     if (!r || NXIntersectsRect(r, &bRect))
  563.     {
  564.         i = buffer->num_ops;
  565.         for (j = 0; j < PTS_GRAPHIC; j++)
  566.             buffer->ops[i++] = 'a';
  567.         buffer->num_ops += PTS_GRAPHIC;
  568.  
  569.         i = buffer->num_pts;
  570.         if (i == 0)
  571.         {        
  572.             [self  getPoint:0  :&pt];
  573.             buffer->pts[i++] = pt.x;
  574.             buffer->pts[i++] = pt.y;
  575.             *lastPoint = pt;
  576.             j = 1;
  577.         }
  578.         else
  579.             j = 0;
  580.  
  581.          for ( ; j < PTS_GRAPHIC + 1; j ++)
  582.         {
  583.             if (j != 4)
  584.             {
  585.                 [self  getPoint:j  :&pt];
  586.                 buffer->pts[i++] = pt.x - lastPoint->x;
  587.                 buffer->pts[i++] = pt.y - lastPoint->y;
  588.                 *lastPoint = pt;
  589.             }
  590.         }
  591.  
  592.         buffer->num_pts += PTS_GRAPHIC*2;
  593.     }
  594.     
  595.     return self;
  596. }
  597.  
  598. /*
  599. *    Draw a box around the file. If imaging write "imaging file..." if not
  600. *    then draw cross hatches. Ideally we would like to draw the file
  601. *    name in the box but obtaining the font metrics for the font is a
  602. *    non-trivial exercise that is incorporated into this application.
  603. */
  604. - drawBoxforRect:(NXRect *) r  imaging:(BOOL) imageFlag
  605. {
  606.     NXAtom        string;
  607.  
  608.     NXSize        strSize;
  609.  
  610.     PSgsave();
  611.     NXRectClip(r);
  612.     PStranslate(bounds.origin.x, bounds.origin.y);
  613.     PSsetgray(NX_LTGRAY);
  614.     PSrectfill(0.0, 0.0, bounds.size.width, bounds.size.height);
  615.  
  616.     if (imageFlag)
  617.     {
  618.         strSize.width = 70;
  619.         strSize.height = 12;
  620.         string = "Imaging file...";
  621.     }
  622.     else
  623.     {
  624.         PSWSetLine(2.0, NX_DKGRAY);
  625.         PSWStrokeX(0.0, 0.0, bounds.size.width, bounds.size.height);
  626.         PSrectstroke(0.0, 0.0, bounds.size.width, bounds.size.height);
  627.         /* Insert code to show the file name. */
  628.         strSize.width = bounds.size.width;
  629.         strSize.height = bounds.size.height;
  630.         string = filename;
  631.     }
  632.  
  633.     if (bounds.size.width > strSize.width && bounds.size.height > strSize.height)
  634.     {
  635.         PSsetgray(NX_BLACK);
  636.         PSmoveto((bounds.size.width - strSize.width)/2, (bounds.size.height - strSize.height)/2);
  637.         PSselectfont("Helvetica",  12);
  638.         PSshow((char *) string);
  639.     }
  640.     PSgrestore();
  641.  
  642.     return self;
  643. }
  644.  
  645. /*
  646.  *    Draws the TIFF or EPS file.  Sets up for drawing in a window if drawing
  647.  *    onscreen and the image is smaller than the maximum window size
  648.  *    permitted.  Makes the window transparent and scales it to the right
  649.  *    size to match the scale of the document.
  650.  */
  651. - drawObject:(NXRect *) r  withFlags:(int) flags  inView:view
  652. {
  653.     BOOL        useImage;
  654.  
  655.     NXRect        rect;
  656.  
  657.     if (!r || NXIntersectsRect(r, &bounds))
  658.     {
  659.         if (flags & REDRAWFLAG)
  660.         {
  661.             PSgsave();
  662.             PStranslate(bounds.origin.x, bounds.origin.y);
  663.             PSWSetLine(1.0, NX_LTGRAY);
  664.             PSrectstroke(0.0, 0.0, bounds.size.width, bounds.size.height);
  665.             PSgrestore();
  666.         }
  667.         else if (gflags.unimageable)
  668.         {
  669.             [self  drawBoxforRect:r  imaging:NO];
  670.             gflags.new = NO;
  671.         }
  672.         else if (NXDrawingStatus == NX_PRINTING ||
  673.                 NXDrawingStatus == NX_COPYING ||
  674.                     [view  image])
  675.         {
  676.             [imagerep  drawIn:&bounds  with:0];
  677.         }
  678.         else
  679.         {
  680.             useImage = YES;
  681.     
  682.             /*
  683.             *    Size the cache.
  684.             */
  685.             [image  getSize:&rect.size];
  686.             if (bounds.size.width!= rect.size.width ||
  687.                 bounds.size.height!= rect.size.height)
  688.             {
  689.                 gflags.dirty = YES;
  690.                 rect.size.width = bounds.size.width;
  691.                 rect.size.height = bounds.size.height;
  692.                 if (rect.size.width < IMAGE_MAX && rect.size.height < IMAGE_MAX)
  693.                 {
  694.                     [image  setSize:&rect.size];
  695.                     [image  getSize:&rect.size];
  696.                 }
  697.                 else
  698.                     useImage = NO;
  699.             }
  700.                 
  701.             if (gflags.dirty)
  702.             {
  703.                 /*
  704.                 *    Draw the gray box that tells the user the file is being imaged.
  705.                 */
  706.                 [view  lockFocus];
  707.                 [self  drawBoxforRect:r  imaging:YES];
  708.                 [view  unlockFocus];
  709.                 [[view  window]  flushWindow];
  710.                 NXPing();
  711.  
  712.                 /*
  713.                 *    Draw the file into an NXImage using an NXEPSImageRep.
  714.                 *    In other words, cache the image offscreen while drawing
  715.                 *    into a separate context.
  716.                 */
  717.                 if (useImage)
  718.                 {
  719.                     rect.origin.x = rect.origin.y = 0;
  720.                     [image  lockFocus];
  721.                     PSsetalpha(0.0);
  722.                     PSsetgray(NX_WHITE);
  723.                     NXRectFill(&rect);
  724.                     PSsetalpha(1.0);
  725.  
  726.                     PStranslate(-bounds.origin.x, -bounds.origin.y);
  727.                 }
  728.  
  729.                 if ([NXApp  tracingFlag])
  730.                     DPSTraceContext(DPSGetCurrentContext(), YES);
  731.  
  732.                 gflags.error = ![imagerep  drawIn:&bounds  with:0];
  733.  
  734.                 if ([NXApp  tracingFlag])
  735.                     DPSTraceContext(DPSGetCurrentContext(), NO);
  736.  
  737.                 if (useImage)
  738.                     [image  unlockFocus];
  739.  
  740.                 if (gflags.error)
  741.                 {
  742.                     gflags.unimageable = YES;
  743.                     [self  displayError];
  744.                     if (!gflags.new)
  745.                         [self  drawBoxforRect:r  imaging:NO];
  746.                 }
  747.             }
  748.  
  749.             if (useImage && !gflags.error)
  750.             {
  751.                 rect.origin.x = rect.origin.y = 0;
  752.                 rect.size.width = bounds.size.width;
  753.                 rect.size.height = bounds.size.height;
  754.                 [image  composite:NX_SOVER  fromRect:&rect  toPoint:&bounds.origin];
  755.             }
  756.  
  757.             gflags.new = NO;
  758.             gflags.dirty = NO;
  759.         }
  760.     }
  761.  
  762.     return self;
  763. }
  764.  
  765. - displayError
  766. {
  767.     NXRunAlertPanel("Imaging Error", ImageErrorString, "OK", NULL, NULL);
  768.  
  769.     return self;
  770. }
  771.  
  772. @end
  773.